package cn.edu.zjut.mina.protocal;

import java.nio.charset.Charset;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;


/** 
 * JMessageProtocal解码 
 * @author Simple 
 * 
 */  
public class JMessageProtocalDecoder extends ProtocolDecoderAdapter {  
  
  private Logger log=Logger.getLogger(JMessageProtocalDecoder.class);  
  
  private Charset charset;  
  
  public JMessageProtocalDecoder(Charset charset) {  
    this.charset=charset;  
  }  
  
  /** 
   * 解码 
   */  
  public void decode(IoSession session, IoBuffer buf, ProtocolDecoderOutput out) throws Exception {  
    JAbsMessageProtocal absMP=null;  
    // 获取协议tag  
    byte tag=buf.get();  
    // 获取协议体长度  
    int length=buf.getInt();  
    // 取出协议体  
    byte[] bodyData=new byte[length];  
    buf.get(bodyData);  
    // 为解析数据做准备  
    // 检测协议  
    IoBuffer tempBuf=IoBuffer.allocate(100).setAutoExpand(true);  
    tempBuf.put(tag);  
    tempBuf.putInt(length);  
    tempBuf.put(bodyData);  
    tempBuf.flip();  
    if(!canDecode(tempBuf)) {  
      return;  
    }  
    // 协议体buf  
    IoBuffer bodyBuf=IoBuffer.allocate(100).setAutoExpand(true);  
    bodyBuf.put(bodyData);  
    bodyBuf.flip();  
    // 整个协议buf  
    IoBuffer allBuf=IoBuffer.allocate(100).setAutoExpand(true);  
    allBuf.put(tag);  
    allBuf.putInt(length);  
    allBuf.put(bodyData);  
    allBuf.flip();  
    //  
    if(tag == JConstant.REQ) {  
      JMessageProtocalReq req=new JMessageProtocalReq();  
      short functionCode=bodyBuf.getShort();  
      String content=bodyBuf.getString(charset.newDecoder());  
      req.setFunctionCode(functionCode);  
      req.setContent(content);  
      absMP=req;  
    } else if(tag == JConstant.RES) {  
      JMessageProtocalRes res=new JMessageProtocalRes();  
      byte resultCode=bodyBuf.get();  
      String content=bodyBuf.getString(charset.newDecoder());  
      res.setResultCode(resultCode);  
      res.setContent(content);  
      absMP=res;  
    } else {  
      log.error("未定义的Tag");  
    }  
    out.write(absMP);  
  }  
  
  // 是否可以解码  
  private boolean canDecode(IoBuffer buf) {  
    int protocalHeadLength=5;// 协议头长度  
    int remaining=buf.remaining();  
    if(remaining < protocalHeadLength) {  
      log.error("错误，协议不完整，协议头长度小于" + protocalHeadLength);  
      return false;  
    } else {  
      log.debug("协议完整");  
      // 获取协议tag  
      byte tag=buf.get();  
      if(tag == JConstant.REQ || tag == JConstant.RES) {  
        log.debug("Tag=" + tag);  
      } else {  
        log.error("错误，未定义的Tag类型");  
        return false;  
      }  
      // 获取协议体长度  
      int length=buf.getInt();  
      if(buf.remaining() < length) {  
        log.error("错误，真实协议体长度小于消息头中取得的值");  
        return false;  
      } else {  
        log.debug("真实协议体长度:" + buf.remaining() + " = 消息头中取得的值:" + length);  
      }  
    }  
    return true;  
  }  
}  
